﻿namespace Fiuba.Algo3.Titiritero
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.ComponentModel;
    using System.Drawing;
    public delegate void Controlador();
    public class ControladorJuego
    {
        public event Controlador Vivieron;
        public bool estaEnEjecucion;
        public double IntervaloSimulacion {get; set;}
        public ISuperficieDeDibujo superficieDeDibujo;
        private IList<IObjetoVivo> objetosVivos;
        private IList<IDibujable> dibujables;
        private Bitmap backGround;
        public IDibujable Presentacion { get; set; }
        public ControladorJuego(ISuperficieDeDibujo superficieDeDibujo, Bitmap backGround)
        {
            this.superficieDeDibujo = superficieDeDibujo;
            this.estaEnEjecucion = false;
            this.IntervaloSimulacion = 2000;
            this.objetosVivos = new List<IObjetoVivo>();
            this.dibujables = new List<IDibujable>();
            this.backGround = backGround;
        }

        public void ComenzarJuego()
        {
            BackgroundWorker delayer = new BackgroundWorker();
            estaEnEjecucion = true;
            delayer.DoWork += new DoWorkEventHandler(delayer_DoWork);
            delayer.RunWorkerAsync();

        }

        void delayer_DoWork(object sender, DoWorkEventArgs e)
        {
            ComenzarAsync();
        }

        public void ComenzarAsync()
        {
            int i = 0;
            while (estaEnEjecucion)
            {
                if (i < 120 && Presentacion != null)
                {
                    MostrarPresentacion(Presentacion);
                }
                else
                {
                    
                    Simular();
                    Vivieron();
                    Dibujar();
                }
                i++;
                Thread.Sleep(TimeSpan.FromMilliseconds(this.IntervaloSimulacion));
            }
        }

        public void DetenerJuego()
        {
            this.estaEnEjecucion = false;
        }
	
        public void agregarObjetoVivo(IObjetoVivo objetoVivo)
        {
            objetosVivos.Add(objetoVivo);
        }
        public void setObjetosVivos(List<IObjetoVivo> objetosVivos)
        {
            this.objetosVivos = objetosVivos;
        }
        public void removerObjetoVivo(IObjetoVivo objetoVivo)
        {
            objetosVivos.Remove(objetoVivo);
        }
        public void setDibujables(List<IDibujable> Dibujables)
        {
            this.dibujables = Dibujables;
        }
        public void agregarDibujable(IDibujable unDibujable)
        {
            dibujables.Add(unDibujable);
        }

        public void removerDibujable(IDibujable unDibujable)
        {
            dibujables.Remove(unDibujable);
        }
        private void MostrarPresentacion(IDibujable unDibujable)
        {
            Graphics grafico = (Graphics)superficieDeDibujo.Buffer;
            unDibujable.Dibujar(grafico);
        }
        public void MostrarImagen(IDibujable unDibujable, int tiempo)
        {
            int i = 0;
            while (i < tiempo)
            {
                Graphics grafico = (Graphics)superficieDeDibujo.Buffer;
                unDibujable.Dibujar(grafico);
                i++;
                Thread.Sleep(TimeSpan.FromMilliseconds(this.IntervaloSimulacion));
            }
            
        }
        private void Dibujar()
        {
            Bitmap bitmap = (Bitmap)backGround.Clone();
            Graphics graficoNew = Graphics.FromImage(bitmap);
            int i = 0;
            while (i < dibujables.Count)
            {
                dibujables[i].Dibujar(graficoNew);
                i++;
            }
            Graphics grafico = (Graphics)superficieDeDibujo.Buffer;
            grafico.DrawImage(bitmap, 0, 0);
        }

        /**
         * Ejecuta la simulacion recorriendo la coleccion de objetivos vivos.
         */
        private void Simular()
        {

            int i = 0;
            int count = objetosVivos.Count;

            while (i < count)
            {
                objetosVivos[i].Vivir();
                i++;
                if (count > objetosVivos.Count)
                {
                    count = objetosVivos.Count;
                }
            }

        }
    }
}
